package com.bit.demo16.TCP;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EchoServer {
    private ServerSocket  serverSocket;
    public EchoServer(int port) throws Exception {
        //服务器启动，就会绑定到port端口上面
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("server start");
        //创建一个可以动态调整大小的线程池
        ExecutorService threadPool= Executors.newCachedThreadPool();
        while (true){
            //serverSocket.accept();监听并接受客户端的连接请求
            //会返回一个 Socket 对象，这个对象代表了与该客户端之间的通信通道
            Socket socket = serverSocket.accept();
            //多线程版本
//            Thread t=new Thread(()->{
//                // 这个地方 this 和 socket 都是 lambda 从外层作用域中捕获的变量.
//                this.processConnection(socket);
//            });
//            t.start();
            //线程池版本
            threadPool.submit(()->{
               processConnection(socket);
            });
        }
    }
    //处理一个客户端/一个连接的逻辑
    private void processConnection(Socket socket){
        System.out.printf("[%s:%d] client online!\n", socket.getInetAddress().toString(), socket.getPort());
        try (InputStream inputStream=socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()){
            // 实现通信的代码.
            // 一个客户端可能会和服务器有多轮的请求响应交互.
            Scanner scanner = new Scanner(inputStream);
            PrintWriter writer=new PrintWriter(outputStream);
            while (true){
                if (!scanner.hasNext()){
                    // 针对客户端下线逻辑的处理. 如果客户端断开连接了 (比如客户端结束了)
                    // 此时 hasNext 就会返回 false
                    // 如果是使用 read 方法, 就会出现返回 -1 的情况. 也可以用来判定客户端断开连接.
                    System.out.printf("[%s:%d] client offline!\n", socket.getInetAddress().toString(), socket.getPort());
                    break;
                }
                // 没有执行到这个打印, 说明上面的 hasNext 没有解除阻塞. 大概率就是客户端没发来数据.
                // System.out.println("服务器收到数据了!");
                String request=scanner.next();
                // 2. 根据请求计算响应.
                String response=process(request);
                // 3. 把响应写回到客户端.
                writer.println(response);
                writer.flush();

                System.out.printf("[%s:%d] req: %s; resp: %s\n", socket.getInetAddress().toString(), socket.getPort(),
                        request, response);
            }
        }catch (Exception e) {
                e.printStackTrace();
        }finally {
            try {
                socket.close();
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws Exception {
        EchoServer echoServer=new EchoServer(9090);
        echoServer.start();
    }
}
